package com.spring.pay.weixin.service.impl;

import java.io.DataInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.spring.common.redis.JedisManager;
import com.spring.pay.alipay.service.impl.AlipayServiceImpl;
import com.spring.pay.weixin.client.ClientCustomSSL;
import com.spring.pay.weixin.config.WeiXinConfig;
import com.spring.pay.weixin.handler.ResponseHandler;
import com.spring.pay.weixin.service.IWeiXinService;
import com.spring.pay.weixin.util.MD5Util;
import com.spring.pay.weixin.util.WXUtil;
import com.spring.pay.weixin.util.XMLUtil;
import com.spring.trade.po.TradeOrderInfo;
import com.spring.trade.service.ITradeOrderInfoService;
import com.spring.util.DateUtils;
import com.spring.util.TradeOrderInfoStatus;
import com.spring.util.constant.Constant;

/**
 * @author 作者 E-mail: liuyang
 * @date 创建时间：2016年10月9日 上午11:38:27
 * @version 2.0
 * @parameter
 * @since
 * @return
 */
@Service
public class WeiXinServiceImpl implements IWeiXinService {
	private Logger LOGGER = Logger.getLogger(AlipayServiceImpl.class);

	@Autowired
	private ITradeOrderInfoService tradeOrderInfoServiceImpl;

/*	@Autowired
	private IDocDoctorInfoService doctorInfoService;

	@Autowired
	private ITradeServiceInfoService tradeServiceInfoService;
	@Autowired
	private IPatientCustomerService patientCustomerService;
	@Autowired
	private IPatientBuyCallService patientBuyCallService;*/

	/**
	 * 根据request得到返回数据(微信回调接口返回的是流,只能用这个方法获取,不能用request.getParameterMap()方法)
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws JDOMException
	 */
	@SuppressWarnings("rawtypes")
	public Map getWeiXinNotifyMap(HttpServletRequest request) throws JDOMException, IOException {

		DataInputStream in = null;
		String wxNotifyXml = "";
		try {
			in = new DataInputStream(request.getInputStream());
			byte[] dataOrigin = new byte[request.getContentLength()];
			in.readFully(dataOrigin); // 根据长度，将消息实体的内容读入字节数组dataOrigin中

			wxNotifyXml = new String(dataOrigin); // 从字节数组中得到表示实体的字符串
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				in.close(); // 关闭数据流
			}
		}
		Map map = XMLUtil.doXMLParse(wxNotifyXml);

		return map;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public String receiveNotify(ResponseHandler resHandler) {

		try {
			// 根据request得到微信返回数据
			Map map = getWeiXinNotifyMap(resHandler.getHttpServletRequest());

			// 判断签名
			if (resHandler.isTenpaySign(map)) {

				// ------------------------------
				// 处理业务开始
				// ------------------------------

				// 处理数据库逻辑
				// 注意交易单不要重复处理
				// 注意判断返回金额

				// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
				TradeOrderInfo info = tradeOrderInfoServiceImpl.selectByorderNo((String) map.get("out_trade_no")); // out_trade_no
				if (info == null) {
					LOGGER.debug("微信回调out_trade_no校验失败！");
					return "faild";
				}

				// 判断订单是否已经处理过
				if (StringUtils.isNotBlank(info.getPayOrderNo())) {
					LOGGER.debug("微信回调通知已处理过！");
					return "faild";
				}

				
				// 判断total_fee是否确实为该订单的实际金额（即商户订单创建时的金额）
				if (info.getOrderMoney().multiply(new BigDecimal(100)).compareTo(new BigDecimal((String) map.get("total_fee"))) != 0) {
					LOGGER.error("微信回调订单金额校验失败！");
					return "faild";
				}
				

				// 返回的微信订单号
				info.setPayOrderNo((String) map.get("transaction_id")); // trade_no
				// 支付类型
				info.setPayType(Constant.wxPay);
				// 微信支付时间
				
				DateFormat DEFAULT_TIME_FORMATER = new SimpleDateFormat("yyyyMMddHHmmss");
				Date date = DateUtils.parseTime((String)map.get("time_end"),DEFAULT_TIME_FORMATER);
				
				info.setPayTime(date);
				// 支付状态
				info.setStatus(TradeOrderInfoStatus.ORDER_PAY.getValue()); // 1已支付

				tradeOrderInfoServiceImpl.updateByPrimaryKeySelective(info);
				
				JedisManager.setObject(info.getOrderNo(), 0, TradeOrderInfoStatus.ORDER_PAY.getValue());
/*				// 得到医生信息
				DocDoctorInfo doctorInfo = doctorInfoService.selectDocDoctorInfoKey(info.getDoctorId());
				// 得到患者信息
				PatientCustomer patientCustomer = patientCustomerService.selectByPrimaryKey(info.getPatientId());
				Integer hourNum = BaseDataInitialize.getMsgCount(1, Constant.IMAGE_TEXT_RULE_HOUR_CODE);
				Integer msgNum = BaseDataInitialize.getMsgCount(1, Constant.IMAGE_TEXT_RULE_NUM_CODE);
				// 得到服务名
				TradeServiceInfo serviceInfo2 = tradeServiceInfoService.selectByPrimaryKey(info.getServiceType());
				// 短信map
				
				LinkedHashMap<String, String> jsonMap =null;
				if(info.getServiceType()==ServiceTypeConstants.TEXT.getValue()){
					jsonMap =new LinkedHashMap<>();
					jsonMap.put("patientName", StringUtils.isBlank(patientCustomer.getName())?"有患者":patientCustomer.getName());
					jsonMap.put("serviceName", serviceInfo2.getName());
					jsonMap.put("hour", hourNum+"");
					jsonMap.put("msgNum", msgNum+"");
					AliSmsService.sendSMS(doctorInfo.getMobile(),jsonMap,AliSmsService.CREATE_ORDER_TEMPID);
				}else if(info.getServiceType()==ServiceTypeConstants.TEL.getValue()){
					CallPatient callPatient =new CallPatient();
					callPatient.setOrderNo(info.getOrderNo());
					CallPatientDto patientDto = patientBuyCallService.getCallPatientInfo(callPatient);
					//患者购买医生电话服务短信--患者端
					jsonMap =new LinkedHashMap<>();
					jsonMap.put("docName", doctorInfo.getName());
					AliSmsService.sendSMS(patientCustomer.getMobile(),jsonMap,AliSmsService.CREATE_TEL_ORDER_PATIENT);
					//患者购买医生电话服务短信--医生端
					jsonMap =new LinkedHashMap<>();
					jsonMap.put("patientName", patientDto.getPatientName());
					jsonMap.put("callTalkTime", info.getCallDuration()+"");
					AliSmsService.sendSMS(doctorInfo.getMobile(),jsonMap,AliSmsService.CREATE_TEL_ORDER_DOCTOR);
					
				}
				
				// ------------------------------
				// 处理业务完毕
				// ------------------------------
				doctorInfoService.updateActiveTime(info.getDoctorId());*/
				return "SUCCESS";

			} else {
				LOGGER.debug("通知签名验证失败");
				return "faild";
			}

		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.error("微信接口系统错误！");
		}
		return "faild";
	}


	@Override
	public String refundRequest(TradeOrderInfo tradeOrderInfoTemp) {
		// 发送请求
		String strResponse = null;
		try {
			String out_trade_no = tradeOrderInfoTemp.getOrderNo();
			TradeOrderInfo info = tradeOrderInfoServiceImpl.selectByorderNo(out_trade_no);
			if (info == null) {
				LOGGER.debug("无法查询到订单查询信息！");
				return "faild";
			}
			
			String resCode = wechatRefund(info.getOrderNo(),info.getOrderMoney().multiply(new BigDecimal(100)).doubleValue());
				
			//微信退款成功
			if (resCode.equals("SUCCESS")) {
				TradeOrderInfo tradeOrderInfo = new TradeOrderInfo();
				tradeOrderInfo.setOrderNo(out_trade_no);
				tradeOrderInfo.setRefundTime(DateUtils.getDate());// 退款时间
				tradeOrderInfo.setStatus(TradeOrderInfoStatus.ORDER_COMPLETE_REFUND.getValue());// 4已退款
				//退款理由
				if(StringUtils.isNotEmpty(tradeOrderInfoTemp.getRefundReason())){
					tradeOrderInfo.setRefundReason(tradeOrderInfoTemp.getRefundReason());
				}
				tradeOrderInfoServiceImpl.updateByPrimaryKeySelective(tradeOrderInfo);
				strResponse = "success";
			} else {
				strResponse = resCode;
			}
		} catch (Exception e) {
			LOGGER.error("微信退款接口出现异常！"+e.getMessage());
			strResponse = "faild";
		}
		return strResponse;
	}
	
	/**
	 * 退款函数，该方法可以对曾经部分退款的订单进行再次退款
	 * @param out_trade_no 商户订单号
	 * @param total_fee1 退款对应的订单的总金额（以“元”为单位）
	 * @param refund_fee1 计划退款的金额（以“元”为单位）
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String wechatRefund(String out_trade_no,double total_fee1,double refund_fee1){
		int total_fee = (int) (total_fee1);//订单的总金额,以分为单位（填错了貌似提示：同一个out_refund_no退款金额要一致）
		int refund_fee = (int) (refund_fee1);// 退款金额，以分为单位（填错了貌似提示：同一个out_refund_no退款金额要一致）
		String nonce_str = WXUtil.getNonceStr();;// 随机字符串
		//微信开发平台应用id
		String appid = WeiXinConfig.APP_ID;
		//退款单号(现在应用没有退款单号,所以退款单号与订单号用同一个)
		String out_refund_no = out_trade_no;
		
		//财付通商户号
		String mch_id = WeiXinConfig.PARTNER;
		//操作员(默认就是商户号)
		String op_user_id = mch_id;
		
		
		Map<String, String> map = new HashMap<String, String>();
		map.put("appid", appid);
		map.put("mch_id", mch_id);
		map.put("nonce_str", nonce_str);
		map.put("out_trade_no", out_trade_no);
		map.put("out_refund_no", out_refund_no);
		map.put("total_fee", total_fee+"");
		map.put("refund_fee", refund_fee+"");
		map.put("op_user_id", op_user_id);
	
		//生成sign
		String sign = MD5Util.md5Sign(map, WeiXinConfig.PARTNER_KEY);
		
		map.put("sign", sign);
		
		//将map转换成微信支持的xml文件格式
		String xmlData = XMLUtil.mapToXml(map);
		
		
		String fail = "faild";
		try {
			//微信退款
			String refundResult= ClientCustomSSL.doRefund(xmlData);
			
			Map xmlMap = XMLUtil.doXMLParse(refundResult);
			//从退款返回信息中取出return_code
			fail = (String) xmlMap.get("return_code");
		
		} catch (Exception e) {
			e.printStackTrace();
			fail = "faild";
		}
		return fail;
	}
	
	/**
	 * 该方法默认全额退款，但如果该订单曾经退款一部分，那么就不可使用该方法
	 * @param out_trade_no 商户订单号
	 * @param total_fee1 总的退款金额（以“元”为单位）
	 */
	public static String wechatRefund(String out_trade_no,double total_fee1){
		return wechatRefund(out_trade_no,total_fee1,total_fee1);
	}

}
